# -*- coding:utf-8 -*-
from django.http import HttpResponseRedirect
from django.db import IntegrityError
from django.views.decorators.csrf import csrf_protect

from annoying.decorators import render_to

from core.forms import LinkForm, ScheduleForm
from core.forms import ProviderForm
from core.forms import VariableForm
from core.forms import SimpleUpload
from core.forms import ProxyServerForm

from app import config

from core.models import Scan
from core.models import Link
from core.models import Result
from core.models import Provider
from core.models import Variable
from core.models import Schedule
from core.models import ProxyServer

@csrf_protect
@render_to('options.html')
def actions(request):
    return {}

@render_to('dashboard.html')
def dashboard(request):
    data = {
        'scan': {
            'length': 'No scans'
        },
        'result': {
            'length': 'No results'
        },
        'links': {
            'length': 'No links'
        },
        'providers': {
            'length': 'No providers'
        },
        'proxies': {
            'length': 'No proxies'
        },
        'schedule': {
            'length': 'No schedules'
        },
        'config': {
            'screenshot': config.MAKE_SCREENSHOTS,
            'quality': config.IMAGE_QUALITY,
            'use_proxy': config.USE_PROXY,
            'supress_prompt': config.SUPPRESS_PROMPT
        }
    }

    if len(Scan.objects.all()):
        data['scan']['length'] = len(Scan.objects.all())

    if len(Result.objects.all()):
        data['result']['length'] = len(Result.objects.all())

    if len(Link.objects.all()):
        data['links']['length'] = len(Link.objects.all())

    if len(Provider.objects.all()):
        data['providers']['length'] = len(Provider.objects.all())

    if len(ProxyServer.objects.all()):
        data['proxies']['length'] = len(ProxyServer.objects.all())

    if len(Schedule.objects.all()):
        data['schedule']['length'] = len(Schedule.objects.all())

    return data

class Lists:
    @classmethod
    def map_action(cls, path):
        action_list = {
            'scan': cls.list_scan,
            'link': cls.list_link,
            'proxyserver': cls.list_proxyserver,
            'provider': cls.list_provider,
            'variable': cls.list_variable,
            'schedule': cls.list_schedule
        }

        return action_list.get(path)

    @classmethod
    def list_scan(cls):
        scans = []
        data = {}

        for scan in Scan.objects.all():
            try:
                results = Result.objects.filter(scan = scan)

                try:
                    provider = scan.provider.name
                except AttributeError:
                    provider = None

                scans.append({'scan': scan, 'provider': provider, 'results': results})
            except Provider.DoesNotExist:
                continue

        data.setdefault('messages', [])
        data.setdefault('scans', scans)

        data['messages'].append({
            'type': 'info',
            'body': 'Scanned packages'
        })

        return data

    @classmethod
    def list_link(cls):
        data = {}
        form = LinkForm()

        links = [item for item in Link.objects.all()]

        data.setdefault('form', form)
        data.setdefault('action', '/link')
        data.setdefault('method', 'POST')
        data.setdefault('name', 'add_link')
        data.setdefault('upload', SimpleUpload())

        data.setdefault('messages', [])

        data['messages'].append({
            'type': 'info',
            'body': 'Existing links (%d)' % len(links)
        })

        data.setdefault('links', links)
        data.setdefault('page_title', 'Existing links (%d)' % len(links))

        return data

    @classmethod
    def list_proxyserver(cls):
        proxies = []
        data = {}

        for item in ProxyServer.objects.all():
            proxies.append(item)

        data.setdefault('form', ProxyServerForm())
        data.setdefault('action', '/proxy')
        data.setdefault('method', 'POST')
        data.setdefault('name', 'add_proxy')

        data.setdefault('messages', [])
        data.setdefault('proxies', proxies)

        data['messages'].append({
            'type': 'info',
            'body': 'Proxy servers (%s)' % len(proxies)
        })

        return data

    @classmethod
    def list_provider(cls):
        data = {}

        providers = [item for item in Provider.objects.all()]

        data.setdefault('form', ProviderForm())
        data.setdefault('action', '/provider')
        data.setdefault('method', 'POST')
        data.setdefault('name', 'add_provider')

        data.setdefault('messages', [])
        data.setdefault('providers', providers)

        data['messages'].append({
            'type': 'info',
            'body': 'Providers (%s)' % len(providers)
        })

        return data

    @classmethod
    def list_variable(cls):
        data = {}

        variables = [item for item in Variable.objects.all()]

        data.setdefault('form', VariableForm())
        data.setdefault('action', '/variable')
        data.setdefault('method', 'POST')
        data.setdefault('name', 'add_variable')

        data.setdefault('messages', [])
        data.setdefault('variables', variables)

        data['messages'].append({
            'type': 'info',
            'body': 'Variables (%s)' % len(variables)
        })

        return data

    @classmethod
    def list_schedule(cls):
        data = {}

        schedules = [item for item in Schedule.objects.all()]

        data.setdefault('form', ScheduleForm())
        data.setdefault('action', '/schedule')
        data.setdefault('method', 'POST')
        data.setdefault('name', 'add_schedule')

        data.setdefault('messages', [])
        data.setdefault('schedules', schedules)

        data['messages'].append({
            'type': 'info',
            'body': 'Variables (%s)' % len(schedules)
        })

        return data

class New:
    @classmethod
    def map_action(cls, path):
        action_list = {
            '/link': cls.new_link,
            '/proxy': cls.new_proxy,
            '/provider': cls.new_provider,
            '/variable': cls.new_variable
        }

        return action_list.get(path)

    @classmethod
    def new_link(cls, request):
        new_link = LinkForm(request.POST)
        data = {}

        data.setdefault('messages', [])

        if new_link.is_valid():
            try:
                new_link.save()

                data['messages'].append({
                    'type': 'info',
                    'body': 'URI successfully saved',
                    'url_text': '(reload)',
                    'url': '/link'
                })
            except IntegrityError:
                data['messages'].append({
                    'type': 'alert',
                    'body': 'Such link already exists'
                })
        else:
            data['messages'].append({
                'type': 'alert',
                'body': 'Incorrect URI'
            })

        return data

    @classmethod
    def new_proxy(cls, request):
        proxy = ProxyServerForm(request.POST)
        data = {}

        data.setdefault('messages', [])

        if proxy.is_valid():
            try:
                proxy.save()

                data['messages'].append({
                    'type': 'info',
                    'body': 'Proxy server successfully saved',
                    'url_text': '(reload)',
                    'url': '/proxy'
                })
            except IntegrityError:
                data['messages'].append({
                    'type': 'alert',
                    'body': 'Such proxy already exists'
                })
        else:
            data['messages'].append({
                'type': 'alert',
                'body': 'Incorrect definition'
            })

        return data

    @classmethod
    def new_provider(cls, request):
        provider = ProviderForm(request.POST)
        data = {}

        data.setdefault('messages', [])

        if provider.is_valid():
            try:
                provider.save()

                data['messages'].append({
                    'type': 'info',
                    'body': 'Provider successfully saved',
                    'url_text': '(reload)',
                    'url': '/provider'
                })
            except IntegrityError:
                data['messages'].append({
                    'type': 'alert',
                    'body': 'Such provider already exists'
                })
        else:
            data['messages'].append({
                'type': 'alert',
                'body': 'Incorrect definition'
            })

        return data

    @classmethod
    def schedule(cls, request):
        pass

    @classmethod
    def new_variable(cls, request):
        variable = VariableForm(request.POST)
        data = {}

        data.setdefault('messages', [])

        if variable.is_valid():
            try:
                variable.save()

                data['messages'].append({
                    'type': 'info',
                    'body': 'Variable successfully saved',
                    'url_text': '(reload)',
                    'url': '/variable'
                })
            except IntegrityError:
                data['messages'].append({
                    'type': 'alert',
                    'body': 'Such variable already exists'
                })
        else:
            data['messages'].append({
                'type': 'alert',
                'body': 'Incorrect definition'
            })

        return data

class Update:
    @classmethod
    def map_action(cls, path):
        action_list = {
            '/view/link': cls.view_link,
            '/view/proxy': cls.view_proxy,
            '/view/provider': cls.view_provider,
            '/view/variable': cls.view_variable
        }

        return action_list.get(path)

    @classmethod
    def view_link(cls, request, id):
        data = {}

        data.setdefault('messages', [])

        item = Link.objects.get(pk = int(id))

        if request.POST.has_key('cancel'):
            return HttpResponseRedirect('/link')

        if request.POST:
            update = LinkForm(request.POST)

            if update.is_valid():
                item.title = request.POST['title']
                item.link = request.POST['link']
                item.dump = request.POST['dump']
                item.screenshot = request.POST['screenshot']

                try:
                    item.save()

                    data['messages'].append({
                        'type': 'lightbulb',
                        'body': 'Link successfully updated'
                    })
                except IntegrityError:
                    data['messages'].append({
                        'type': 'alert',
                        'body': 'There was a problem while saving: %s' % item
                    })
            else:
                data['messages'].append({
                    'type': 'alert',
                    'body': 'Incorrect URI'
                })

        form = LinkForm({
            'title': item.title,
            'link': item.link,
            'screenshot': item.screenshot,
            'dump': item.dump
        })

        data.setdefault('form', form)
        data.setdefault('action', '/view/link/%s' % id)
        data.setdefault('method', 'POST')
        data.setdefault('name', 'add_link')

        data['messages'].append({
            'type': 'info',
            'body': item
        })

        return data

    @classmethod
    def view_proxy(cls, request, id):
        data = {}

        data.setdefault('messages', [])

        item = ProxyServer.objects.get(pk = int(id))

        if request.POST.has_key('cancel'):
            return HttpResponseRedirect('/proxy')

        if request.POST:
            update = ProxyServerForm(request.POST)

            if update.is_valid():
                item.host = request.POST['host']
                item.port = request.POST['port']
                item.user = request.POST['user']
                item.password = request.POST['password']
                item.use = request.POST['use']

                try:
                    item.save()

                    data['messages'].append({
                        'type': 'lightbulb',
                        'body': 'Proxy successfully updated'
                    })
                except IntegrityError:
                    data['messages'].append({
                        'type': 'alert',
                        'body': 'There was a problem while saving: %s' % item
                    })
            else:
                data['messages'].append({
                    'type': 'alert',
                    'body': 'Incorrect definition'
                })

        form = ProxyServerForm({
            'host': item.host,
            'port': item.port,
            'user': item.user,
            'password': item.password,
            'use': item.use
        })

        data.setdefault('form', form)
        data.setdefault('action', '/view/proxy/%s' % id)
        data.setdefault('method', 'POST')
        data.setdefault('name', 'add_proxy')

        data['messages'].append({
            'type': 'info',
            'body': item
        })

        return data

    @classmethod
    def view_provider(cls, request, id):
        data = {}

        data.setdefault('messages', [])

        item = Provider.objects.get(pk = int(id))

        if request.POST.has_key('cancel'):
            return HttpResponseRedirect('/provider')

        if request.POST:
            update = ProviderForm(request.POST)

            if update.is_valid():
                item.name = request.POST['name']
                item.ip_range = request.POST['ip_range']

                try:
                    item.save()

                    data['messages'].append({
                        'type': 'lightbulb',
                        'body': 'Provider successfully updated'
                    })
                except IntegrityError:
                    data['messages'].append({
                        'type': 'alert',
                        'body': 'There was a problem while saving: %s' % item
                    })
            else:
                data['messages'].append({
                    'type': 'alert',
                    'body': 'Incorrect definition'
                })

        form = ProviderForm({
            'name': item.name,
            'ip_range': item.ip_range
        })

        data.setdefault('form', form)
        data.setdefault('action', '/view/provider/%s' % id)
        data.setdefault('method', 'POST')
        data.setdefault('name', 'add_provider')

        data['messages'].append({
            'type': 'info',
            'body': '%s: %s' % (item.name, item.ip_range)
        })

        return data

    @classmethod
    def view_variable(cls, request, id):
        data = {}

        data.setdefault('messages', [])

        item = Variable.objects.get(pk = int(id))

        if request.POST.has_key('cancel'):
            return HttpResponseRedirect('/variable')

        if request.POST:
            update = VariableForm(request.POST)

            if update.is_valid():
                item.key = request.POST['key']
                item.value = request.POST['value']

                try:
                    item.save()

                    data['messages'].append({
                        'type': 'lightbulb',
                        'body': 'Variable successfully updated'
                    })
                except IntegrityError:
                    data['messages'].append({
                        'type': 'alert',
                        'body': 'There was a problem while saving: %s' % item
                    })
            else:
                data['messages'].append({
                    'type': 'alert',
                    'body': 'Incorrect definition'
                })

        form = VariableForm({
            'key': item.key,
            'value': item.value
        })

        data.setdefault('form', form)
        data.setdefault('action', '/view/variable/%s' % id)
        data.setdefault('method', 'POST')
        data.setdefault('name', 'add_variable')

        data['messages'].append({
            'type': 'info',
            'body': '%s: %s' % (item.key, item.value)
        })

        return data
